﻿using Photo.Application.System.Authorize.Dto;
using Photo.Core.SeedData;
using System.Security.Claims;

namespace Photo.Application.System.Authorize
{
    /// <summary>
    /// 系统权限验证
    /// </summary>
    [ApiDescriptionSettings(ApiGroupConsts.System, Module = ApiGroupConsts.System)]
    public class AuthorizeService : IDynamicApiController
    {
        /// <summary>
        /// 用户id
        /// </summary>
        private string UserId { get; set; }
        private readonly IRepository<SysUserEntity> _sysUserRepository;
        private readonly IRepository<SysRoleEntity> _sysRoleRepository;
        private readonly IRepository<SysUserRoleEntity> _sysUserRoleRepository;
        private readonly IRepository<SysRoleMenuEntity> _sysRoleMenuRepository;
        public AuthorizeService(IRepository<SysUserEntity> sysUserRepository, IRepository<SysRoleEntity> sysRoleRepository, IRepository<SysUserRoleEntity> sysUserRoleRepository, IRepository<SysRoleMenuEntity> sysRoleMenuRepository)
        {
            UserId = App.User?.FindFirstValue("UserId");
            _sysUserRepository = sysUserRepository;
            _sysRoleRepository = sysRoleRepository;
            _sysUserRoleRepository = sysUserRoleRepository;
            _sysRoleMenuRepository = sysRoleMenuRepository;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous]
        public async Task<LoginOutput> Login(LoginInput input)
        {
            return await MutexUtil.MutexNoWait("/api/system/authorize/login?" + input.Account, async () =>
            {
                var encryptPassword = MD5Encryption.Encrypt(input.Password);
                var entity = await _sysUserRepository.GetAsync(o => o.Account == input.Account && o.Password == encryptPassword, "用户名或密码不正确");

                entity.LastLoginTime = DateTime.Now;

                await _sysUserRepository.UpdateAsync(entity);

                //生成token
                var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
                {
                    { "UserId", entity.Id },// 存储Id
                    { "Account", entity.Account },// 存储用户名
                });

                //生成 刷新token(1天有效期)
                var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken);

                var httpContext = App.HttpContext;

                //设置响应报文头
                httpContext.Response.Headers["access-token"] = accessToken;
                httpContext.Response.Headers["x-access-token"] = refreshToken;

                return new LoginOutput
                {
                    AccessToken = accessToken,
                    RefreshToken = refreshToken
                };
            });
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task ChangePwd(ChangePwdInput input)
        {
            await MutexUtil.MutexNoWait("/api/system/authorize/changepwd?" + UserId, async () =>
            {
                //旧密码加密
                var oldEncryptPassword = MD5Encryption.Encrypt(input.OldPassword);
                //新密码加密
                var newEncryptPassword = MD5Encryption.Encrypt(input.NewPassword);

                var entity = await _sysUserRepository.GetAsync(UserId, "当前用户不存在");
                if (entity.Password != oldEncryptPassword)
                    throw Oops.Oh("原密码输入错误，请联系管理员处理");

                entity.Password = newEncryptPassword;

                await _sysUserRepository.UpdateAsync(entity);
            });
        }

        /// <summary>
        /// 获取当前用户拥有的菜单
        /// </summary>
        /// <returns></returns>
        public async Task<List<SysMenuDto>> GetMenuList()
        {
            //1.获取用户关联角色
            var userRoleIds = await _sysUserRoleRepository.GetFieldListAsync(o => o.UserId == UserId, o => o.RoleId);

            //2.获取角色关联菜单id
            var roleMenuIds = await _sysRoleMenuRepository.GetFieldListAsync(o => userRoleIds.Contains(o.RoleId), o => o.MenuId);

            //3.筛选树列表
            var list = SysMenuSeedData.GetMenuTree(roleMenuIds);

            return list;
        }

        /// <summary>
        /// 获取当前用户菜单按钮列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<string>> GetMenuBtnList(BaseInput input)
        {
            //1.获取用户关联角色
            var userRoleIds = await _sysUserRoleRepository.GetFieldListAsync(o => o.UserId == UserId, o => o.RoleId);

            //2.获取角色关联菜单id
            var roleMenuIds = await _sysRoleMenuRepository.GetFieldListAsync(o => userRoleIds.Contains(o.RoleId), o => o.MenuId);

            //3.获取当前页面id下的所有按钮
            var btnList = SysMenuSeedData.SeedDataList
                .Where(o => o.PUnique == input.Content)
                .Where(o => o.Type == "btn")
                .Where(o => roleMenuIds.Contains(o.Unique))
                .Select(o => o.Unique)
                .Distinct()
                .ToList();

            return btnList;
        }

        /// <summary>
        /// 获取当前登录用户详情
        /// </summary>
        /// <returns></returns>
        public async Task<CurrentUserDto> GetCurrentUserInfo()
        {
            var userInfo = await _sysUserRepository.GetAsync<CurrentUserDto>(UserId, "当前用户不存在");

            var roleIds = await _sysUserRoleRepository.GetFieldDistinctListAsync(o => o.RoleId);

            var roleNameList = await _sysRoleRepository.GetFieldDistinctListAsync(o => roleIds.Contains(o.Id), o => o.Name, o => o.CreationTime, OrderByType.Desc);

            userInfo.RoleNames = string.Join(",", roleNameList);

            return userInfo;
        }


    }
}